package org.reliablesource.prism.gef.editor.actions;

import java.util.Iterator;

import org.eclipse.core.runtime.Platform;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.reliablesource.prism.core.IPrismAnnotation;
import org.reliablesource.prism.core.IPrismScreen;
import org.reliablesource.prism.gef.editor.PrismScreenEditor;
import org.reliablesource.prism.gef.editor.commands.ConnectionCreateCommand;
import org.reliablesource.prism.gef.editor.commands.CreateBendpointCommand;
import org.reliablesource.prism.gef.editor.commands.PointerLocationCreateCommand;
import org.reliablesource.prism.gef.editor.commands.StickyNoteCreateCommand;
import org.reliablesource.prism.gef.editor.model.PointerLocation;
import org.reliablesource.prism.gef.editor.model.ScreenAdapter;
import org.reliablesource.prism.gef.editor.model.StickyNoteAdapter;
import org.reliablesource.prism.gef.editor.model.Wire;
import org.reliablesource.prism.gef.editor.parts.ScreenEditPart;

/**
 * @author Dennis Park
 */
public class OpenPrismScreenAction extends Action implements
		IObjectActionDelegate, IWorkbenchWindowActionDelegate {

	StructuredSelection selection;

	IWorkbenchWindow window;

	/**
	 * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#dispose()
	 */
	public void dispose() {
	}

	/**
	 * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#init(org.eclipse.ui.IWorkbenchWindow)
	 */
	public void init(IWorkbenchWindow _window) {
		window = _window;
	}

	/**
	 * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
	 */
	public void run(IAction action) {

		try {
			final IWorkbenchWindow activeWorkbenchWindow = PlatformUI
					.getWorkbench().getActiveWorkbenchWindow();
			IWorkbenchPage page = activeWorkbenchWindow.getActivePage();

			if (selection.getFirstElement() instanceof IPrismScreen) {
				IEditorPart screenPart = page.openEditor(
						(IEditorInput) Platform.getAdapterManager()
								.getAdapter(selection.getFirstElement(),
										IEditorInput.class),
						PrismScreenEditor.ID, true);
				IPrismScreen screen = (IPrismScreen) selection
						.getFirstElement();
				PointerLocation start = null;
				PointerLocation end = null;
				ScreenAdapter rootScreen = ((ScreenAdapter) ((((ScreenEditPart) ((PrismScreenEditor) screenPart)
						.getGfxViewer().getRootEditPart().getContents())))
						.getModel());
				
//				GraphicalViewer viewer = ((PrismScreenEditor) screenPart).getGfxViewer();
				
				// Start - Re-create a restored Tutorial.
				if (screen.getPointerStart() != null
						&& screen.getPointerStart().getX() != -1) {

					//	Create the Prism Model Element adapter object.
					start = new PointerLocation(new Point(screen
							.getPointerStart().x, screen.getPointerStart().y),
							new Dimension(20, 20));
					
					//	Construct & execute the command.
					new PointerLocationCreateCommand(start, rootScreen,
							new Rectangle(start.getJLocation().x, start
									.getJLocation().y, -1, -1)).execute();
				}
				if (screen.getPointerEnd() != null
					&& screen.getPointerEnd().getX() != -1 && 
						!(screen.getPointerStart().x == screen.getPointerEnd().x 
						&& screen.getPointerStart().y == screen.getPointerEnd().y)) {
					
					//	Create the Prism Model Element adapter object.
					end = new PointerLocation(
							new Point(screen.getPointerEnd().x, screen
									.getPointerEnd().y), new Dimension(20, 20));
					
					//	Construct & execute the command.					
					new PointerLocationCreateCommand(end, rootScreen,
							new Rectangle(end.getJLocation().x, end
									.getJLocation().y, -1, -1)).execute();
				}

				//	Restore the connection path start -> end
				if (start != null && end != null && !(end.getJLocation().x == start.getJLocation().x && end.getJLocation().y == start.getJLocation().y)) {
					
					//	Create the connection command and execute the command.
					ConnectionCreateCommand createConn = new ConnectionCreateCommand(
							start, Wire.SOLID_CONNECTION);
					createConn.setTarget(end);
					createConn.execute();
					
					//	Restore bendpoints between the start & end point.
					if(screen.getPathLocationsList() != null && screen.getPathLocationsList().size() > 0){
						
						//	Acquire reference to Wire object from the connection
						//		create command.
						final Wire connection = createConn.getConnection();
						Iterator bpIt = screen.getPathLocationsList().iterator();
						int i = 0;				
						
						//	Iterate through the locations list
						while(bpIt.hasNext()){
							java.awt.Point pt = (java.awt.Point)bpIt.next();
							Point location = new Point(pt.x, pt.y);
							
							//	Create the bendpoint command, set mandatory
							//		values.
							CreateBendpointCommand bpCmd = new CreateBendpointCommand(rootScreen);
							bpCmd.setWire(connection);
							bpCmd.setIndex(i);
							
							bpCmd.setLocation(location);
							Point ref1 = start.getLocation();
							Point ref2 = end.getLocation();
							
							//	Calculate relative dimensions
							bpCmd.setRelativeDimensions(location.getDifference(ref1),
											location.getDifference(ref2));
							bpCmd.execute();
							i++;
						}
					}
				}

				//	Restore sticky notes
				Iterator<IPrismAnnotation> anotationIter = screen.getAnnotationsList().iterator();
				while (anotationIter.hasNext()) {
					IPrismAnnotation note = anotationIter	.next();
					StickyNoteAdapter noteObject = new StickyNoteAdapter(note,
							note.getLocation().x, note.getLocation().y);
					noteObject.setPropertyValue(IPrismAnnotation.TEXT, note
							.getText());
					noteObject.setPropertyValue(IPrismAnnotation.DIMENSIONS,
							new Rectangle(note.getLocation().x, note
									.getLocation().y, note.getWidth(), note
									.getHeight()));
					new StickyNoteCreateCommand(noteObject, rootScreen,
							new Rectangle(noteObject.getLocation().x,
									noteObject.getLocation().y, noteObject
											.getSize().width, noteObject
											.getSize().height)).execute();
				}

			}
			page.showView(IPageLayout.ID_PROP_SHEET);

		} catch (PartInitException e) {
			e.printStackTrace();
		}
	}

	/**
	 * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction,
	 *      org.eclipse.jface.viewers.ISelection)
	 */
	public void selectionChanged(IAction action, ISelection _selection) {
		selection = (StructuredSelection) _selection;
		action.setEnabled(selection.getFirstElement() instanceof IPrismScreen);
	}

	public void setActivePart(IAction action, IWorkbenchPart targetPart) {
	}

}
